import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.Gson;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import LunaServer.core.LunaServer;
import LunaServer.routing.Route;
import LunaServer.util.VerificationCodeManager;

/**
 * 注册路由处理器
 * 处理/register路径的请求
 */
public class RegisterRoute implements Route {
    private final LunaServer server;

    public RegisterRoute(LunaServer server) {
        this.server = server;
    }
    
    /**
     * 处理HTTP请求
     * 
     * @param exchange HttpExchange对象
     * @return 响应内容
     */
    public String handleRequest(HttpExchange exchange) throws IOException {
        String path = exchange.getRequestURI().getPath();
        
        if ("POST".equals(exchange.getRequestMethod())) {
            // 读取请求体
            String requestBody = "";
            try (InputStream is = exchange.getRequestBody()) {
                requestBody = new String(is.readAllBytes(), StandardCharsets.UTF_8);
            }

            if ("/register/send-email-code".equals(path)) {
                // 发送验证码
                return handleSendVerificationCode(exchange, requestBody);
            } else if ("/register/verify".equals(path)) {
                // 验证验证码，并注册用户
                return handleVerifyAndRegister(exchange, requestBody);
            } else {
                // 未知路径
                return handleNotFound(exchange);
            }
        } else {
            // 方法不允许
            return handleMethodNotAllowed(exchange);
        }
    }

    /**
     * 处理发送验证码请求
     */
    private String handleSendVerificationCode(HttpExchange exchange, String requestBody) throws IOException {
        Gson gson = new Gson();
        Map<String, String> requestData = gson.fromJson(requestBody, Map.class);
        String email = requestData.get("email");
        // 处理错误
        if (email == null || email.isEmpty()) {
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("code", "400");
            errorResult.put("error", "邮箱地址不能为空");
            errorResult.put("time", Instant.now().toString());
            
            String response = gson.toJson(errorResult);
            exchange.getResponseHeaders().set("Content-Type", "application/json");
            exchange.sendResponseHeaders(400, response.getBytes(StandardCharsets.UTF_8).length);
            
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes(StandardCharsets.UTF_8));
            os.close();
            return null;
        }

        // 生成验证码
        String verificationCode = VerificationCodeManager.generateAndStoreCode(email, 6);

        // TODO: 实际项目中需要配置邮件服务并发送验证码到用户邮箱
        // 这里暂时只是生成并存储验证码，模拟发送邮件成功

        Map<String, Object> responseMap = new HashMap<>();
        responseMap.put("code", "200");
        responseMap.put("message", "验证码已生成，值为: " + verificationCode + "（实际项目中会发送到您的邮箱）");
        responseMap.put("time", Instant.now().toString());

        String response = gson.toJson(responseMap);
        exchange.getResponseHeaders().set("Content-Type", "application/json");
        exchange.sendResponseHeaders(200, response.getBytes(StandardCharsets.UTF_8).length);

        OutputStream os = exchange.getResponseBody();
        os.write(response.getBytes(StandardCharsets.UTF_8));
        os.close();
        return null;
    }

    /**
     * 处理验证验证码并注册用户请求
     */
    private String handleVerifyAndRegister(HttpExchange exchange, String requestBody) throws IOException {
        Gson gson = new Gson();
        Map<String, String> registerData = gson.fromJson(requestBody, Map.class);
        
        String username = registerData.get("username");
        String passwordHashedSHA256 = registerData.get("passwordHashedSHA256");
        String email = registerData.get("email");
        String verificationCode = registerData.get("verificationCode");
        
        // 验证验证码
        if (email == null || email.isEmpty() || verificationCode == null || verificationCode.isEmpty()) {
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("code", "400");
            errorResult.put("error", "邮箱和验证码不能为空");
            errorResult.put("time", Instant.now().toString());
            String response = gson.toJson(errorResult);
            exchange.getResponseHeaders().set("Content-Type", "application/json");
            exchange.sendResponseHeaders(400, response.getBytes(StandardCharsets.UTF_8).length);
            
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes(StandardCharsets.UTF_8));
            os.close();
            return null;
        }
        VerificationCodeManager.VerificationResult verificationResult = VerificationCodeManager.verifyCode(email, verificationCode);
        if (!verificationResult.isValid) {
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("code", "400");
            errorResult.put("error", verificationResult.message);
            errorResult.put("time", Instant.now().toString());
            String response = gson.toJson(errorResult);
            exchange.getResponseHeaders().set("Content-Type", "application/json");
            exchange.sendResponseHeaders(400, response.getBytes(StandardCharsets.UTF_8).length);
            
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes(StandardCharsets.UTF_8));
            os.close();
            return null;
        } 
        // 在注册用户之前先检查有没有同名用户，当前逻辑为直接注册 - 该函数有内置。
        RegisterResult result = registerUser(username, passwordHashedSHA256, email);
        
        Map<String, Object> responseMap = new HashMap<>();
        if (result.success) {
            responseMap.put("code", "200");
            responseMap.put("token", "token_for_" + username); // 示例token
            responseMap.put("time", Instant.now().toString());
            
            String response = gson.toJson(responseMap);
            exchange.getResponseHeaders().set("Content-Type", "application/json");
            exchange.sendResponseHeaders(200, response.getBytes(StandardCharsets.UTF_8).length);
            
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes(StandardCharsets.UTF_8));
            os.close();
            return null;
        }
        if (result.isDuplicate) {
            // 用户名已存在
            responseMap.put("code", "409");
            responseMap.put("error", "用户名或邮箱已存在");
            responseMap.put("time", Instant.now().toString());
            
            String response = gson.toJson(responseMap);
            exchange.getResponseHeaders().set("Content-Type", "application/json");
            exchange.sendResponseHeaders(409, response.getBytes(StandardCharsets.UTF_8).length);
            
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes(StandardCharsets.UTF_8));
            os.close();
            return null;
        } else {
            // 系统错误
            responseMap.put("code", "500");
            responseMap.put("error", "注册失败: " + result.errorMessage);
            responseMap.put("time", Instant.now().toString());
            
            String response = gson.toJson(responseMap);
            exchange.getResponseHeaders().set("Content-Type", "application/json");
            exchange.sendResponseHeaders(500, response.getBytes(StandardCharsets.UTF_8).length);
            
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes(StandardCharsets.UTF_8));
            os.close();
            return null;
        }
    }

    /**
     * 在数据库中注册新用户，有内置检查用户名和邮箱的存在性。
     *
     * @param username 用户名
     * @param passwordHashedSHA256 SHA256哈希后的密码
     * @param email 邮箱地址
     * @return 注册结果
     */
    private RegisterResult registerUser(String username, String passwordHashedSHA256, String email) {
        // 从LunaServer实例获取数据库连接参数
        String dbUrl = server.getDbUrl();
        String dbUser = server.getDbUser();
        String dbPass = server.getDbPass();

        // 先检查用户名或邮箱是否已存在
        if (isUserExists(username, email, dbUrl, dbUser, dbPass)) {
            return new RegisterResult(false, true, "用户名或邮箱已存在");
        }

        String sql = "INSERT INTO users (username, password, email, age, is_active) VALUES (?, ?, ?, 0, true)";

        try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPass);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {

            pstmt.setString(1, username);
            // 我需要将密码再sha256一次
            pstmt.setString(2, passwordHashedSHA256); // 实际应用中应该对密码进行加盐哈希处理
            pstmt.setString(3, email);

            int rowsAffected = pstmt.executeUpdate();
            return new RegisterResult(rowsAffected > 0, false, null);

        } catch (SQLException e) {
            System.err.println("Database error during registration: " + e.getMessage());
            e.printStackTrace();
            return new RegisterResult(false, false, e.getMessage());
        }
    }
    
    /**
     * 检查用户名或邮箱是否已存在
     *
     * @param username 用户名
     * @param email 邮箱
     * @param dbUrl 数据库URL
     * @param dbUser 数据库用户名
     * @param dbPass 数据库密码
     * @return 如果用户已存在返回true，否则返回false
     */
    private boolean isUserExists(String username, String email, String dbUrl, String dbUser, String dbPass) {
        String checkSql = "SELECT COUNT(*) FROM users WHERE username = ? OR email = ?";
        
        try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPass);
             PreparedStatement pstmt = conn.prepareStatement(checkSql)) {
            
            pstmt.setString(1, username);
            pstmt.setString(2, email);
            
            try (java.sql.ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    return rs.getInt(1) > 0;
                }
            }
        } catch (SQLException e) {
            System.err.println("Database error during user existence check: " + e.getMessage());
            e.printStackTrace();
        }
        return false; // 出现异常时默认不存在（避免阻止用户注册）
    }
    
    /**
     * 注册结果封装类
     */
    private static class RegisterResult {
        final boolean success;
        final boolean isDuplicate;
        final String errorMessage;
        
        RegisterResult(boolean success, boolean isDuplicate, String errorMessage) {
            this.success = success;
            this.isDuplicate = isDuplicate;
            this.errorMessage = errorMessage;
        }
    }
}